﻿using System;
using System.Buffers;

namespace eNets.IO.Buf;

public sealed class BufferOptions<T>
{
    public static readonly BufferOptions<T> Default = new BufferOptions<T>(); 
    
    
    private const int DefaultMinimumSegmentSize = 4096;
    
    public BufferOptions(MemoryPool<T> pool = null, long pauseWriterThreshold = -1, long resumeWriterThreshold = -1, int minimumSegmentSize = -1)
    {
        MinimumSegmentSize = minimumSegmentSize == -1 ? DefaultMinimumSegmentSize : minimumSegmentSize;
        InitialSegmentPoolSize = 4;
        MaxSegmentPoolSize = 256;
        const int DefaultPauseWriterThreshold = 65536;
        const int DefaultResumeWriterThreshold = DefaultPauseWriterThreshold / 2;

        if (pauseWriterThreshold == -1)
        {
            pauseWriterThreshold = DefaultPauseWriterThreshold;
        }
        else if (pauseWriterThreshold < 0)
        {
            throw new ArgumentOutOfRangeException(ExceptionArgument.pauseWriterThreshold.ToString());
        }

        if (resumeWriterThreshold == -1)
        {
            resumeWriterThreshold = DefaultResumeWriterThreshold;
        }
        else if (resumeWriterThreshold == 0)
        {
            resumeWriterThreshold = 1;
        }

        if (resumeWriterThreshold < 0 || (pauseWriterThreshold > 0 && resumeWriterThreshold > pauseWriterThreshold))
        {
            throw new ArgumentOutOfRangeException(ExceptionArgument.resumeWriterThreshold.ToString());
        }

        Pool = pool ?? MemoryPool<T>.Shared;
        IsDefaultSharedMemoryPool = Pool == MemoryPool<T>.Shared;
        PauseWriterThreshold = pauseWriterThreshold;
        ResumeWriterThreshold = resumeWriterThreshold;
    }

    

    /// <summary>Gets the number of bytes in the <see cref="System.IO.Pipelines.Pipe" /> when <see cref="System.IO.Pipelines.PipeWriter.FlushAsync(System.Threading.CancellationToken)" /> starts blocking.</summary>
    /// <value>The number of bytes in the <see cref="System.IO.Pipelines.Pipe" /> when <see cref="System.IO.Pipelines.PipeWriter.FlushAsync(System.Threading.CancellationToken)" /> starts blocking.</value>
    public long PauseWriterThreshold { get; }

    /// <summary>Gets the number of bytes in the <see cref="System.IO.Pipelines.Pipe" /> when <see cref="System.IO.Pipelines.PipeWriter.FlushAsync(System.Threading.CancellationToken)" /> stops blocking.</summary>
    /// <value>The number of bytes in the <see cref="System.IO.Pipelines.Pipe" /> when <see cref="System.IO.Pipelines.PipeWriter.FlushAsync(System.Threading.CancellationToken)" /> stops blocking.</value>
    public long ResumeWriterThreshold { get; }

    /// <summary>Gets the minimum size of the segment requested from the <see cref="System.IO.Pipelines.PipeOptions.Pool" />.</summary>
    /// <value>The minimum size of the segment requested from the <see cref="System.IO.Pipelines.PipeOptions.Pool" />.</value>
    public int MinimumSegmentSize { get; }
    

    

    /// <summary>Gets the <see cref="System.Buffers.MemoryPool{T}" /> object used for buffer management.</summary>
    /// <value>A pool of memory blocks used for buffer management.</value>
    public MemoryPool<T> Pool { get; }

    /// <summary>
    /// Returns true if Pool is <see cref="MemoryPool{Byte}"/>.Shared
    /// </summary>
    internal bool IsDefaultSharedMemoryPool { get; }

    /// <summary>
    /// The initialize size of the segment pool
    /// </summary>
    internal int InitialSegmentPoolSize { get; }

    /// <summary>
    /// The maximum number of segments to pool
    /// </summary>
    internal int MaxSegmentPoolSize { get; }
}

internal enum ExceptionArgument
{
    minimumSize,
    bytes,
    callback,
    options,
    pauseWriterThreshold,
    resumeWriterThreshold,
    sizeHint,
    destination,
    buffer,
    source,
    readingStream,
    writingStream,
}

enum ResultFlags : byte
{
    None = 0x0,
    Canceled = 0x1,
    Completed = 0x2
}